/*
 PMProfileList.m
 Date Created: February 16, 2010
 
 Author: Karol Krizka <kkrizka@gmail.com>
 
 Copyright (C) 2010 Green-Power
 
 URL: http://code.google.com/p/green-power
 
 This program is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation; either version 3 of the License, or
 (at your option) any later version.
 
 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
 $Id$
 */

#import "PMProfileList.h"


@implementation PMProfileList

@synthesize managedObjectContext;

- (PMProfileList *)initWithManagedObjectContext:(NSManagedObjectContext *)myManagedObjectContext {
  self = [super init];
  if( !self )
    return nil;
  
  [self setManagedObjectContext:myManagedObjectContext];
  return self;
}

- (BOOL)deleteProfile:(NSString*)profileName {
  PMProfile *profile=[self profileForName:profileName];
  if(!profile) return NO;
  if(profile.active) return NO;
 
  // This deletes the profile, along with any associated objects like
  // recycling log and scores. This is because the relationship has been set
  // as cascade.
  [self.managedObjectContext deleteObject:profile];
  
  [self save];
  
  return YES;
}

- (PMProfile *)createProfile:(NSString*)profileName {
  if(![self isProfileNameValid:profileName] ||
     ![self isProfileNameUnique:profileName])
    return nil;
  
  PMProfile *profile=(PMProfile *)[NSEntityDescription insertNewObjectForEntityForName:@"Profile" 
                                                                inManagedObjectContext:[self managedObjectContext]];
  [profile setProfileName:profileName];

  // If this is the first profile created, make it the active one
  if([[self listAllProfiles] count]==1) {
    NSLog(@"Set as Active profile..");
    // This is the only profile, so activate it
    [profile setActive:YES];
  }
  
  if(![self save]) {
    NSLog(@"Error saving new profile.."); 
  }
  
  return profile;
}  
  
- (BOOL)save {
  NSError *error;
  if(![managedObjectContext save:&error]) {
    return NO;
  }
  
  return YES;
}

- (PMProfile *)activeProfile {
  // Setup a fetch request to get the active profile
  NSFetchRequest *fetchRequest=[[NSFetchRequest alloc] init];
  NSEntityDescription *profileEntity=[NSEntityDescription entityForName:@"Profile" inManagedObjectContext:[self managedObjectContext]];
  [fetchRequest setEntity:profileEntity];
  
  // Predicate to only select the active profile
  NSPredicate *activePredicate=[NSPredicate predicateWithFormat:@"active != 0"];
  [fetchRequest setPredicate:activePredicate];
  
  NSError *error;
  NSArray *profileList = [managedObjectContext executeFetchRequest:fetchRequest error:&error];
  [fetchRequest release];
  
  if( !profileList )
  {
    //TODO Handle error
    NSLog(@"Error fetching active profile!");
  }
  
  if([profileList count]==0)
  {
    NSLog(@"No active profile!");
    return nil;
  }
  
  if([profileList count]>1)
  {
    NSLog(@"Multiple active profiles!");
    return nil;
  }
  
  PMProfile *activeProfile=(PMProfile *)[profileList objectAtIndex:0];
  
  return activeProfile;
}

- (void)setActiveProfile:(PMProfile *)newActiveProfile {
  if(self.activeProfile == newActiveProfile) return; // Nothing new
  self.activeProfile.active=NO;
  newActiveProfile.active=YES;
  
  [self save];
}

- (PMProfile *)profileForName:(NSString *)profileName {
  // Setup a fetch request to get the active profile
  NSFetchRequest *fetchRequest=[[NSFetchRequest alloc] init];
  NSEntityDescription *profileEntity=[NSEntityDescription entityForName:@"Profile" 
                                                 inManagedObjectContext:[self managedObjectContext]];
  [fetchRequest setEntity:profileEntity];
  
  // Predicate to only select the active profile
  NSPredicate *namePredicate=[NSPredicate predicateWithFormat:@"profileName == %@",profileName];
  [fetchRequest setPredicate:namePredicate];
  
  NSError *error;
  NSArray *profileList = [managedObjectContext executeFetchRequest:fetchRequest error:&error];
  [fetchRequest release];
  
  if( !profileList ) {
    //TODO Handle error
    NSLog(@"Error fetching profile with name %@!",profileName);
    return nil;
  }
  
  if([profileList count]==0) {
    NSLog(@"No profile named %@!",profileName);
    return nil;
  }

  if([profileList count]>1) {
    NSLog(@"Warning: More than one profile match the name %@. Returning first one.",profileName);
  }

  return [profileList objectAtIndex:0];
}

- (NSArray *)listAllProfiles {
  // Setup a fetch request to get the number of profiles
  NSFetchRequest *request=[[NSFetchRequest alloc] init];
  NSEntityDescription *profileEntity=[NSEntityDescription entityForName:@"Profile" inManagedObjectContext:[self managedObjectContext]];
  [request setEntity:profileEntity];
  
  NSError *error;
  NSArray *profileList = [managedObjectContext executeFetchRequest:request error:&error];
  if(profileList == nil)
  {
    //TODO Handle error!
    NSLog(@"Error fetching profile list!");
  }
  
  [request release];
  
  return profileList;
}

- (BOOL)isProfileNameValid:(NSString *)profileName {
  BOOL isNonEmpty=([profileName length]>0);
  
  NSMutableCharacterSet *allowedCharacterSet=[[NSCharacterSet alphanumericCharacterSet] mutableCopy];
	[allowedCharacterSet formUnionWithCharacterSet:[NSCharacterSet whitespaceCharacterSet]];
	
  NSCharacterSet *nowAllowedCharacterSet=[allowedCharacterSet invertedSet];
  
  BOOL isValid=([profileName rangeOfCharacterFromSet:nowAllowedCharacterSet].location==NSNotFound);
  
  [allowedCharacterSet release];
  
  return isValid && isNonEmpty;
}

- (BOOL)isProfileNameUnique:(NSString *)profileName
{
  NSFetchRequest *request=[[NSFetchRequest alloc] init];
  
  NSEntityDescription *entity = [NSEntityDescription entityForName:@"Profile" inManagedObjectContext:[self managedObjectContext]];
  [request setEntity:entity];
  
  NSPredicate *uniqPredicate=[NSPredicate predicateWithFormat:@"profileName like %@",profileName];
  [request setPredicate:uniqPredicate];
  
  NSError *error;
  NSUInteger numResults = [managedObjectContext countForFetchRequest:request error:&error];

  [request release];
  
  return (numResults == 0);
}

@end
